import Sortable from '@timluo465/react-sortablejs';
import { observer } from "mobx-react";
import React from "react";
import { findDOMNode } from "react-dom";
import { DragKey } from "../../../../constants/form";
import { getDragInfo } from "../../../../utils/drag";
import FBFooterView from "../component/form-footer/View";
import FBHeaderView from "../component/form-header/View";
import { onMove } from '../sortable';
import FieldView from "./view";

const Divider = ({ visible, color }) => {
  if (!visible) return null;

  return <div style={{ borderBottom: `1px solid ${color}`}} />
};
// 禁止拖动的选择器
const disabledDragSelector = '.f-tablelayout td'; // 表格布局的单元格

@observer
export default class FBMain extends React.Component {
  starting = false;

  constructor(props) {
    super();

    this.state = {
      paddingBottom: 60,
      minHeight: 0,
    };
    this.store = props.store;
    this.onClick = _.memoize(this.onClick.bind(this));
    this.handleMinHeight = _.debounce(this.calcHeight.bind(this), 300);
  }

  componentDidMount() {
    const footer = findDOMNode(this.footer);

    this.calcHeight();
    this.setState({ paddingBottom: footer.offsetHeight });

    window.addEventListener('resize', this.handleMinHeight);
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleMinHeight);
  }

  calcHeight() {
    const borderWidth = 2;
    const mainPadding = 32; // wea-edc-form-main的padding-top和padding-bottom
    const { container } = this.props;
    const headerHeight = findDOMNode(this.header).offsetHeight;
    const footerHeight = findDOMNode(this.footer).offsetHeight;
    const minHeight = $(container).height() - headerHeight - mainPadding * 2 - footerHeight - borderWidth * 2;
    const MIN_HEIGHT = 632;

    this.setState({ minHeight: minHeight >= MIN_HEIGHT ? minHeight : MIN_HEIGHT });
  }

  // uuid 作为memoize的默认resolver
  onClick(uuid, com) {
    if (!this.store.canSelect(com)) {
      return () => { };
    }

    return () => {
      this.store.onSelectedIdChange(uuid);
    }
  }

  onDragEnd = (e) => {
    const { oldIndex, newIndex, to } = e;
    const dragInfo = getDragInfo(to);

    if (dragInfo) {
      return this.store.dragComponentToWrapper(dragInfo, oldIndex);
    }
    
    this.store.onSortable({ oldIndex, newIndex });
  }

  onDragStart = () => {
    this.starting = true;
  }

  onDragMove = evt => {
    if (this.starting) return this.starting = false;

    return onMove(evt);
  }

  onDragAdd = e => {
    const { newIndex, item } = e;
    const dragInfo = getDragInfo(item)

    if (!dragInfo) return;

    this.store.addNewComponentFromWrapper(dragInfo, newIndex);
  }

  renderFBody() {
    const { components, onRemove, selectedId } = this.store;
    const { minHeight } = this.state;

    if (!minHeight) return null;

    return (
      <div className='wea-edc-form-body' style={{ minHeight }}>
        <Sortable ecId={`${this && this.props && this.props.ecId || ''}_Sortable@oqdx2v`} 
          style={{ minHeight }}
          onChange={() => { }}
          options={{
            chosenClass: 'wea-edc-dragging',
            animation: 60,
            swapThreshold: 0.5,
            direction: 'vertical',
            group: {
              name: DragKey.COM,
              put: true,
              pull: true
            },
            supportPointer: false,
            filter: disabledDragSelector,
            onStart: this.onDragStart,
            onEnd: this.onDragEnd,
            onAdd: this.onDragAdd,
            onMove: this.onDragMove
          }}
        >
          {components.map(com => (
            <FieldView ecId={`${this && this.props && this.props.ecId || ''}_FieldView@onjuz3@${com.uuid}`}
              field={com}
              selectedKey={selectedId}
              onRemove={onRemove}
              components={components}
              onClick={this.onClick(com.uuid, com)} 
              onPropsChange={this.store.onPropsChange}
              renderItem={this.renderItem}
              onCopy={this.store.copyField}
            />
          ))}
        </Sortable>
      </div>
    );
  }

  renderItem = com => {
    if (!com) return null;
    
    const { onRemove, selectedId, components } = this.store;

    return (
      <FieldView ecId={`${this && this.props && this.props.ecId || ''}_FieldView@bvmjxo`} 
        field={com}
        components={components}
        selectedKey={selectedId}
        onRemove={onRemove}
        onClick={this.onClick(com.uuid)}
      />
    );
  }

  render() {
    const { paddingBottom } = this.state;
    const { formHeader, formFooter } = this.store;
    const { form } = this.props;

    return (
      <div style={Object.assign(form.css, form.border.css)}>
        <FBHeaderView ecId={`${this && this.props && this.props.ecId || ''}_FBHeaderView@osxh19`}
          data={formHeader.config}
          ref={header => this.header = header}
          onClick={this.onClick(formHeader.uuid)}
        />
        <Divider ecId={`${this && this.props && this.props.ecId || ''}_Divider@2pbj46`} {...form.divider} />
        <div style={{ position: 'relative', paddingBottom }}>
          {this.renderFBody()}
          <Divider ecId={`${this && this.props && this.props.ecId || ''}_Divider@mjn3ez`} {...form.divider} />
          <FBFooterView ecId={`${this && this.props && this.props.ecId || ''}_FBFooterView@7tr8ra`}
            data={formFooter.config}
            ref={footer => this.footer = footer}
            onClick={this.onClick(formFooter.uuid)}
          />
        </div>
      </div>
    );
  }
}